package com.quwan.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.quwan.app.service.ActivityService;
import com.quwan.app.vo.SignInDTO;
import com.quwan.common.Check;
import com.quwan.common.enums.CommonStatus;
import com.quwan.common.exception.ExpCode;
import com.quwan.common.exception.ResponseException;
import com.quwan.entity.TDdLog;
import com.quwan.entity.TMember;
import com.quwan.mapper.TDdLogMapper;
import com.quwan.mapper.TMemberMapper;
import com.quwan.utils.NumberUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author quan
 * @date 2021-11-21 16:02
 */

@Service
@RequiredArgsConstructor
public class ActivityServiceImpl implements ActivityService {
    private final TDdLogMapper ddLogMapper;
    private final TMemberMapper memberMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer activitySignIn(String mId) {

        Integer randomDD = NumberUtils.randomScopeNum(1, 11);
        TDdLog ddLog = ddLogMapper.selectOne(
                new LambdaQueryWrapper<TDdLog>()
                        .select(TDdLog::getDay, TDdLog::getDd)
                        .eq(TDdLog::getMId, mId)
                        .eq(TDdLog::getType, 1)
                        .eq(TDdLog::getDay, LocalDate.now())
        );
        if (ddLog != null)
            return ddLog.getDd().intValue();

        int row = ddLogMapper.insert(
                new TDdLog()
                        .setDd(Long.parseLong(randomDD + ""))
                        .setTips("签到活动")
                        .setType(1)
                        .setMId(Long.parseLong(mId))
                        .setDay(LocalDate.now())
        );
        Integer mRow = memberMapper.updateDDBymId(mId, randomDD);
        if (row == 1 && mRow == 1)
            return randomDD;
        else
            throw new ResponseException(ExpCode.OPERATE_FAIL.getCode(), ExpCode.OPERATE_FAIL.getMsg());
    }


    @Override
    public SignInDTO ddSignList(String id) {
        LocalDate monday = LocalDate.now().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        LocalDate sunday = LocalDate.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
        SignInDTO res = new SignInDTO();
        TMember member = memberMapper.selectOne(new LambdaQueryWrapper<TMember>()
                .select(TMember::getDd)
                .eq(TMember::getId, id));
        Check.notNull(member, ExpCode.MEMBER_NOT_EXIST);
        res.setDd(member.getDd());
        List<TDdLog> logs =
                ddLogMapper
                        .selectList(
                                new LambdaQueryWrapper<TDdLog>()
                                        .select(TDdLog::getDay)
                                        .eq(TDdLog::getMId, id)
                                        .eq(TDdLog::getType, 1)
                                        .between(TDdLog::getDay, monday, sunday)
                        );
        Set<Integer> weekSet =
                logs
                        .stream()
                        .map(m -> m.getDay().getDayOfWeek().getValue())
                        .collect(Collectors.toSet());

        List<SignInDTO.Item> items =
                IntStream.range(1, 8)
                        .mapToObj(m -> {
                            SignInDTO.Item sign = res.getItem().setSignIn(0).setWeek(m);
                            if (weekSet.contains(m))
                                sign.setSignIn(CommonStatus.NORMAL.getType());
                            return sign;
                        }).collect(Collectors.toList());
        res.setWeeks(items);

        int index = 1;
        int pageSize = 31;
        int pageNo = 0;
        Integer maxCount = 0;
        LocalDate endTime = null; //最后签到时间

        do {
            List<TDdLog> days = ddLogMapper.selectList(
                    new LambdaQueryWrapper<TDdLog>()
                            .select(TDdLog::getDay)
                            .eq(TDdLog::getMId, id)
                            .eq(TDdLog::getType, 1)
                            .orderByDesc(TDdLog::getDay)
                            .last(new StringBuffer(" limit ")
                                    .append(pageNo)
                                    .append(" , ")
                                    .append(pageSize).toString())
            );

            //签到数据 为空 总数为0 结果为0
            if (CollectionUtils.isEmpty(days))
                return res.setContinuous(maxCount);
            //查询数据 是否有当天记录 有 代表已经签到
            if (LocalDate.now().isEqual(days.get(0).getDay())) {
                res.setTodaySignIn(true);
                // maxCount++;
                //最后签到时间 当天
                endTime = LocalDate.now();
            }
            //当前没有签到 记录是否有昨天签到记录
            else if (maxCount == 0 && LocalDate.now().minusDays(1).isEqual(days.get(0).getDay())) {
                //最后签到时候 昨天
                endTime = days.get(0).getDay();
            }

            if (endTime != null) {
                for (int i = 0; i < days.size(); i++) {
                    if (endTime.minusDays(i).isEqual(days.get(i).getDay())) {
                        maxCount++;
                    } else
                        return res.setContinuous(maxCount);

                }
                if (days.size() < pageSize)
                    return res.setContinuous(maxCount);
            }
            endTime = days.get(days.size() - 1).getDay().minusDays(1);

            pageNo = (++index - 1) * pageSize;

        } while (true);

    }
}
